#ifndef _QUADTREE_H_
#define _QUADTREE_H_

#include <vector>
#include "Vector.h"

namespace QuadTreeLib
{

#define MAX_LODLEVEL 15

class QuadTreeNode;

struct LODSelection
{
	float mLodRanges[MAX_LODLEVEL];
	Vector3 mCamPos;
	Plane mFrustums[6];
	std::vector<QuadTreeNode *> mSelectedNodes;

	LODSelection(size_t maxNodes)
	{
		mSelectedNodes.reserve(maxNodes);
	}

	void resetSelection()
	{
		// clear() doesn't resize the reserved size
		mSelectedNodes.clear();
	}
};

class QuadTree
{
public:
	QuadTree(size_t maxLevel)
		: mMaxLODLevel(maxLevel)
	{
		if (maxLevel > MAX_LODLEVEL)
			mMaxLODLevel = MAX_LODLEVEL;
	}
	virtual ~QuadTree() {}

	QuadTreeNode* getNode(size_t index) const
	{
		if (index > mNodes.size())
			return 0;
		return mNodes[index];
	}

	void setNumNodes(size_t n)
	{
		if (n > mNodes.size())
		{
			mNodes.reserve(n);
		}
	}

	size_t getNumNodes() const
	{
		return mNodes.size();
	}

	void addNode(QuadTreeNode* node)
	{
		mNodes.push_back(node);
	}

	void setVisibleRanges(size_t n, const float visibleRanges[])
	{
		if (n > MAX_LODLEVEL)
			n = MAX_LODLEVEL;
		memcpy(mVisibleRanges, visibleRanges, n * sizeof(float));
	}

	void setVisibleRange(size_t level, float range)
	{
		if (level >= MAX_LODLEVEL)
			return;
		mVisibleRanges[level] = range;
	}

	void LODSelect(LODSelection& lodSelection);

private:
	std::vector<QuadTreeNode*> mNodes;
	size_t mMaxLODLevel;
	float mVisibleRanges[MAX_LODLEVEL];
};

} // namespace QuadTreeLib
#endif